﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using openxml.butter.definition;

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.CustomXmlDataProperties;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.CustomProperties;
using DocumentFormat.OpenXml.VariantTypes;

using StudioLib;

namespace openxml.butter.controller
{
    /// <summary>
    /// Classe utilitaire gérant la préparation des modèles modifiables
    /// </summary>
    public class WebTemplateFactory
    {

        #region Properties

        /// <summary>
        /// Url de la page générant l'arbre des données dispos pour le modèles
        /// </summary>
        public String treeTemplateUrl { get; set; }


        /// <summary>
        /// Url de mise à jour du modèle
        /// </summary>
        public String UpdateUrl { get; set; }

        /// <summary>
        /// Url du webservice
        /// </summary>
        public String WebServiceUrl { get; set; }

        /// <summary>
        /// Url du modèle de document dédié à l'édition avec macro et ruban spécial à attacher
        /// </summary>
        public String SpecialTemplateUrl { get; set; }

        #endregion

        #region Methodes
        //reset des customProperties existantes
        private void resetCustomProperties(CustomFilePropertiesPart part)
        {
            StudioTrace.WriteLine("dans le reset:" + ( part!=null) );
            part.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties();
            part.Properties.AddNamespaceDeclaration("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");

        }


        /// <summary>
        /// Ajouter une CustomProperty au document
        /// </summary>
        /// <param name="part"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <param name="order"></param>
        /// <returns></returns>
        private CustomDocumentProperty AddStringCustomProperty(CustomFilePropertiesPart part,String name, String value, int order)
        {
            //les properties à modifier 
            Properties properties = part.Properties;
 
            //créer la propriété elle même
            CustomDocumentProperty customDocumentProperty1 = new CustomDocumentProperty() { FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", PropertyId = order, Name =name };
            
            //le contenu
            VTLPWSTR vTLPWSTR1 = new VTLPWSTR();
            vTLPWSTR1.Text = value ;
            customDocumentProperty1.Append(vTLPWSTR1);
            
            //ajouter
            properties.Append(customDocumentProperty1);

            return customDocumentProperty1;

        }
        /// <summary>
        /// Préparer le modèle modifié pour édition
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public byte[] PrepareTemplate(DocumentTemplate dt )
        {

            byte[] arrBytes = null;
            try
            {
                StudioTrace.WriteLine("début du prépare");
                
                //créer un mémory stream resizable ( sans donnée au départ )
                System.IO.MemoryStream MS = new MemoryStream();

                //charger le modele dans un Document OpenXML
                MS.Write(dt.BinaryContent, 0,(int) dt.BinaryContent.Length);
               
                StudioTrace.WriteLine("chargement en mémoire");
               
                using (WordprocessingDocument doc = WordprocessingDocument.Open( MS,true ))
                {
                    
                    StudioTrace.WriteLine("chargement openxml");

                    doc.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);

                    StudioTrace.WriteLine("chgt de type de document");

                    //attacher le modèle ruban via this.SpecialTemplateURL                   
                    AttachedTemplate attachedTemplate1 = new AttachedTemplate() { Id = "rubanOXB"};
                    
                    MainDocumentPart mainPart = doc.MainDocumentPart;
                    DocumentSettingsPart documentSettingsPart1 = mainPart.DocumentSettingsPart;
                    documentSettingsPart1.Settings.Append(attachedTemplate1);

                    //passer l'url du template
                    documentSettingsPart1.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate",
                        new Uri(this.SpecialTemplateUrl + "?guid=" + Guid.NewGuid().ToString(), UriKind.Absolute), "rubanOXB");

                    mainPart.Document.Save();
                    StudioTrace.WriteLine("modèle attaché");

                    //package contenant les properties
                    CustomFilePropertiesPart propsPart = doc.CustomFilePropertiesPart;

                    if (propsPart == null)
                    {
                        StudioTrace.WriteLine("ajout de la part properties");
                        propsPart = doc.AddCustomFilePropertiesPart();
                        
                    }

                    StudioTrace.WriteLine("avant reset props : " + ( propsPart != null) );

                    //ménage des props pour l'ordre
                    resetCustomProperties(propsPart );

                    StudioTrace.WriteLine("reset props");

                    //ajouter la propriété UpdateURL : wtf-upload-url
                    AddStringCustomProperty(propsPart, "wtf-upload-url",this.UpdateUrl + dt.Code, 2 );

                    //ajouter la propriété WebServiceURL : oxb-ws
                    AddStringCustomProperty(propsPart, "oxb-ws", this.WebServiceUrl, 3);

                    //ajouter la propriété Code : template-code
                    AddStringCustomProperty(propsPart, "template-code", dt.Code, 4);


                    //ajouter la propriété url de la page gérant l'arbre des données pour le modèle : treeTemplateUrl
                    AddStringCustomProperty(propsPart, "tree-data-template-url", this.treeTemplateUrl + "?code=" + dt.Code, 5);

                    StudioTrace.WriteLine("prop 3");
                    propsPart.Properties.Save();
                    
                    StudioTrace.WriteLine("props add & save");

                    mainPart.Document.Save();
                    doc.Close();
                                       
                }
                
               
                StudioTrace.WriteLine("fin du doc");
                //MS.Flush();
                long size = MS.Length;
                arrBytes = new byte[size];
                arrBytes = MS.ToArray();

                MS.Close();
                StudioTrace.WriteLine("lecture nouveau binaire :" + size);

                
                StudioTrace.WriteLine("fin du prépare");

                return arrBytes;
            }
            catch (Exception e)
            {
                throw new Exception("pb dans le prepare du modèle : " + e.Message);
                return null;
            }
        }

        #endregion

    }
}
